<template>
    <div class="image-uploader">
        <el-upload
            v-model:file-list="fileList"
            :accept="accept"
            :action="action"
            :before-upload="beforeUpload"
            :class="{ 'hide-upload': shouldHideUpload }"
            :data="data"
            :headers="headers"
            :limit="limit"
            :list-type="listType"
            :multiple="multiple"
            :on-error="handleError"
            :on-remove="handleRemove"
            :on-success="handleSuccess"
        >
            <!-- 自定义上传按钮 -->
            <template #trigger>
                <div class="custom-upload-btn">
                    <slot name="uploadBtn">
                        <el-icon :size="iconSize">
                            <Plus />
                        </el-icon>
                        <span v-if="btnText" class="btn-text">{{ btnText }}</span>
                    </slot>
                </div>
            </template>

            <!-- 图片预览模板 -->
            <template #file="{ file }">
                <div class="preview-item">
                    <img
                        :src="handleUrl(file.url)"
                        class="preview-image"
                        @click="handlePreview(file)"
                    />
                    <div class="preview-mask">
            <span class="preview-actions">
              <el-icon @click="handlePreview(file)"><ZoomIn /></el-icon>
              <el-icon @click="handleRemove(file)"><Delete /></el-icon>
            </span>
                    </div>
                </div>
            </template>
        </el-upload>

        <!-- 图片预览弹窗 -->
        <el-dialog v-model="previewVisible" title="图片预览" width="60%">
            <img :src="handleUrl(previewImage)" class="full-preview-image" />
        </el-dialog>

        <!-- 上传进度弹窗 -->
        <el-dialog
            v-if="showProgress"
            v-model="uploadingVisible"
            :close-on-click-modal="false"
            title="上传进度"
            width="500px"
        >
            <div class="upload-progress-list">
                <div v-for="file in uploadingFiles" :key="file.uid" class="progress-item">
                    <div class="file-name">{{ file.name }}</div>
                    <el-progress
                        :percentage="file.percentage || 0"
                        :status="file.status === 'exception' ? 'exception' : undefined"
                    />
                </div>
            </div>
        </el-dialog>
    </div>
</template>

<script lang="ts">
import { computed, defineComponent, ref, watch } from 'vue'
import type { UploadFile, UploadFiles, UploadProgressEvent } from 'element-plus'
import { ElMessage } from 'element-plus'
import { Delete, Plus, ZoomIn } from '@element-plus/icons-vue'
import config from '@/config'
import { RequestCodeEnum } from '@/enums/requestEnums'
import useAppStore from '@/stores/modules/app'
import useUserStore from '@/stores/modules/user'
import feedback from '@/utils/feedback'
import { handleUrl } from '@/utils/util'

export default defineComponent({
    name: 'ImageUploader',
    components: { Plus, ZoomIn, Delete },
    props: {
        modelValue: {
            type: Array as () => UploadFiles,
            default: () => []
        },
        limit: {
            type: Number,
            default: 9
        },
        maxSize: {
            type: Number,
            default: 5 // 单位MB
        },
        listType: {
            type: String,
            default: 'picture-card'
        },
        btnText: String,
        iconSize: {
            type: Number,
            default: 24
        },
        type: {
            type: String,
            default: 'image'
        },
        multiple: {
            type: Boolean,
            default: true
        },
        data: {
            type: Object,
            default: () => ({})
        },
        showProgress: {
            type: Boolean,
            default: false
        }
    },
    emits: ['update:modelValue', 'success', 'error', 'change'],
    setup(props, { emit }) {
        const userStore = useUserStore()
        const appStore = useAppStore()

        // 核心数据
        const fileList = computed({
            get: () => props.modelValue,
            set: (val) => emit('update:modelValue', val)
        })

        // 预览相关
        const previewVisible = ref(false)
        const previewImage = ref('')
        const previewCache = ref<Record<string, string>>({})

        // 上传进度相关
        const uploadingVisible = ref(false)
        const uploadingFiles = ref<UploadFile[]>([])

        // 配置项
        const action = ref(`${config.baseUrl}${config.urlPrefix}/upload/${props.type}`)
        const headers = computed(() => ({
            token: userStore.token,
            version: appStore.config.version
        }))
        const accept = computed(() => {
            switch (props.type) {
                case 'image':
                    return '.jpg,.png,.gif,.jpeg,.ico'
                case 'video':
                    return '.wmv,.avi,.mpg,.mpeg,.3gp,.mov,.mp4,.flv,.rmvb,.mkv'
                default:
                    return '*'
            }
        })

        // 上传前校验
        const beforeUpload = (file: UploadFile) => {
            const isOverSize = file.size! > props.maxSize * 1024 * 1024
            if (isOverSize) {
                ElMessage.error(`文件大小不能超过${props.maxSize}MB`)
                return false
            }
            return true
        }

        // 图片预览处理
        const handlePreview = (file: UploadFile) => {
            if (!file.url && file.raw) {
                previewCache.value[file.uid] = URL.createObjectURL(file.raw)
            }
            previewImage.value = file.url || previewCache.value[file.uid]
            previewVisible.value = true
        }

        // 文件删除处理
        const handleRemove = (file: UploadFile) => {
            const index = fileList.value.findIndex(f => f.uid === file.uid)
            if (index > -1) {
                const newList = [...fileList.value]
                newList.splice(index, 1)
                fileList.value = newList
                emit('change', newList)
            }

            // 释放预览缓存
            if (previewCache.value[file.uid]) {
                URL.revokeObjectURL(previewCache.value[file.uid])
                delete previewCache.value[file.uid]
            }
        }

        // 上传成功处理
        const handleSuccess = (response: any, file: UploadFile) => {
            if (response.code === RequestCodeEnum.SUCCESS) {
                file.url = response.data.url
                emit('success', { file, response })
                checkAllDone()
                console.log('Upload success:', fileList)
            } else {
                handleError(new Error(response.msg || '上传失败'), file)
            }
        }

        // 错误处理（完整实现）
        const handleError = (error: Error, file: UploadFile) => {
            console.error('Upload error:', error)

            // 更新文件状态
            const target = fileList.value.find(f => f.uid === file.uid)
            if (target) {
                target.status = 'exception'
                target.percentage = 100
            }

            // 显示错误提示
            const message = error.message || '文件上传失败'
            feedback.msgError(`${file.name}: ${message}`)

            // 释放预览缓存
            if (previewCache.value[file.uid]) {
                URL.revokeObjectURL(previewCache.value[file.uid])
                delete previewCache.value[file.uid]
            }

            // 触发事件
            emit('error', { file, error })
            checkAllDone()
        }

        // 进度处理
        const handleProgress = (event: UploadProgressEvent, file: UploadFile) => {
            if (props.showProgress) {
                uploadingVisible.value = true
                const target = uploadingFiles.value.find(f => f.uid === file.uid)
                if (!target) {
                    uploadingFiles.value.push(file)
                }
            }
        }

        // 检查全部上传完成
        const checkAllDone = () => {
            if (props.showProgress) {
                const done = fileList.value.every(f =>
                    f.status === 'success' || f.status === 'exception'
                )
                if (done) {
                    setTimeout(() => {
                        uploadingVisible.value = false
                        uploadingFiles.value = []
                    }, 1500)
                }
            }
        }

        // 自动清理预览缓存
        watch(fileList, (newList, oldList) => {
            const removed = oldList.filter(f => !newList.find(nf => nf.uid === f.uid))
            removed.forEach(file => {
                if (previewCache.value[file.uid]) {
                    URL.revokeObjectURL(previewCache.value[file.uid])
                    delete previewCache.value[file.uid]
                }
            })
        })

        const shouldHideUpload = computed(() => {
            return fileList.value.length >= props.limit
        })

        return {
            fileList,
            previewVisible,
            previewImage,
            uploadingVisible,
            uploadingFiles,
            action,
            headers,
            accept,
            beforeUpload,
            handlePreview,
            handleRemove,
            handleSuccess,
            handleError,
            handleProgress,
            shouldHideUpload,
            handleUrl
        }
    }
})
</script>

<style lang="scss" scoped>
.image-uploader {
    :deep(.el-upload-list__item) {
        transition: all 0.3s;

        &:hover {
            .preview-mask {
                opacity: 1;
            }
        }
    }

    .preview-item {
        position: relative;
        width: 100%;
        height: 100%;

        .preview-image {
            width: 100%;
            height: 100%;
            object-fit: cover;
            border-radius: 6px;
        }

        .preview-mask {
            position: absolute;
            top: 0;
            left: 0;
            width: 100%;
            height: 100%;
            background: rgba(0, 0, 0, 0.5);
            opacity: 0;
            transition: opacity 0.3s;
            display: flex;
            align-items: center;
            justify-content: center;

            .preview-actions {
                color: white;
                font-size: 20px;
                display: flex;
                gap: 12px;

                .el-icon {
                    cursor: pointer;
                    transition: transform 0.3s;

                    &:hover {
                        transform: scale(1.2);
                    }
                }
            }
        }
    }

    .custom-upload-btn {
        display: flex;
        flex-direction: column;
        align-items: center;
        justify-content: center;
        width: 100px;
        height: 100px;
        border: 1px dashed var(--el-border-color);
        border-radius: 6px;
        cursor: pointer;
        transition: border-color 0.3s;

        &:hover {
            border-color: var(--el-color-primary);
            color: var(--el-color-primary);
        }

        .btn-text {
            margin-top: 8px;
            font-size: 12px;
        }
    }

    .full-preview-image {
        width: 100%;
        max-height: 70vh;
        object-fit: contain;
    }

    .hide-upload :deep(.el-upload) {
        display: none;
    }

    .upload-progress-list {
        padding: 0 20px;

        .progress-item {
            margin-bottom: 20px;

            .file-name {
                margin-bottom: 8px;
                font-size: 14px;
                color: var(--el-text-color-regular);
            }
        }
    }
}
</style>
